/*
 * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "cmsis_os2.h"
#include "iot_errno.h"
#include "iot_uart.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"
#include "ohos_init.h"
#include "lwip/sockets.h"
#include "wifi_connect.h"

#define UART_TASK_STACK_SIZE (1024 * 8)
#define UART_TASK_PRIO 25
#define UART_BUFF_SIZE 17
#define WIFI_IOT_UART_IDX_1 1
#define TASK_DELAY_2S 1000000

#define TASK_STACK_SIZE (1024 * 10)
#define CONFIG_WIFI_SSID "23B"    // 要连接的WiFi 热点账号
#define CONFIG_WIFI_PWD "18126169529"  // 要连接的WiFi 热点密码
#define CONFIG_CLIENT_PORT 8888      // 要连接的服务器端口
#define TCP_BACKLOG 10
#define GPIO_1 14
#define GPIO_2 7



// char recvbuf[512];
char *buf = "Hello! I'm BearPi-HM_Nano TCP Server!";

static const char *send_data = "YuchuanHuaying TCP Client Send Data.";

/**
 * @brief 主函数线程
 *
 */
static void Hi3861_demo(void)
{
    uint8_t uart_buff[UART_BUFF_SIZE] = { 0 };
    uint8_t *uart_buff_ptr = uart_buff;
    uint8_t ret;
    IotGpioDir gpioDir;
    IotGpioValue gpiovalue;

    IotUartAttribute uart_attr = {

        // baud_rate: 9600
        .baudRate = 9600,

        // data_bits: 8bits
        .dataBits = 8,
        .stopBits = 1,
        .parity = 0,
    };

    //NULLptr
    if(&uart_attr==NULL){
        printf("kongzhizhen\n");
    }

    // 串口初始化
    ret = IoTUartInit(WIFI_IOT_UART_IDX_1, &uart_attr);
    if (ret != IOT_SUCCESS) {
        printf("Failed to init uart! Err code = %d\n", ret);
        return;
    }
    
    //gpio1初始化
    IoTGpioInit(GPIO_1);
    IoTGpioSetFunc(GPIO_1,IOT_GPIO_FUNC_GPIO_14_GPIO);
    IoTGpioSetDir(GPIO_1, IOT_GPIO_DIR_OUT);
    IoTGpioGetDir(GPIO_1,&gpioDir);
    printf("IotGpioDir is %d\n",gpioDir);
    IoTGpioGetOutputVal(GPIO_1,&gpiovalue);
    printf("GpioGetOutputValue is %d\n",gpiovalue);

    //gpio2
    IoTGpioInit(GPIO_2);
    IoTGpioSetFunc(GPIO_2,IOT_GPIO_FUNC_GPIO_7_GPIO);
    IoTGpioSetDir(GPIO_2, IOT_GPIO_DIR_OUT);
    IoTGpioGetDir(GPIO_2,&gpioDir);
    printf("IotGpioDir is %d\n",gpioDir);
    IoTGpioGetOutputVal(GPIO_2,&gpiovalue);
    printf("GpioGetOutputValue is %d\n",gpiovalue);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
    // 在sock_fd 进行监听，在 new_fd 接收新的链接
    int sock_fd, new_fd;

    // 服务端地址信息
    struct sockaddr_in server_sock;

    // 客户端地址信息
    struct sockaddr_in client_sock, *cli_addr;
    int sin_size;

    // 连接Wifi
    WifiConnect(CONFIG_WIFI_SSID, CONFIG_WIFI_PWD);

    // 创建socket
    if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket is error\r\n");
        exit(1);
    }
    bzero(&server_sock, sizeof(server_sock));
    server_sock.sin_family = AF_INET;
    server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
    server_sock.sin_port = htons(CONFIG_CLIENT_PORT);

    // 调用bind函数绑定socket和地址
    if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1) {
        exit(1);
    }

    // 调用listen函数监听(指定port监听)
    if (listen(sock_fd, TCP_BACKLOG) == -1) {
        exit(1);
    }

    printf("start accept\n");
    while(1){
        sin_size = sizeof(struct sockaddr_in);

        if ((new_fd = accept(sock_fd, (struct sockaddr *)&client_sock, (socklen_t *)&sin_size)) == -1) {
            perror("accept");
            continue;
        }

        cli_addr = malloc(sizeof(struct sockaddr));

        printf("accept addr\r\n");

        if (cli_addr != NULL) {
            int ret;
            if ((ret = memcpy_s(cli_addr, sizeof(struct sockaddr), &client_sock, sizeof(struct sockaddr))) != 0) {
                perror("memcpy_s is error\r\n");
                exit(1);
            }
        }
        // 处理目标
        ssize_t ret;
        
        while (1) {
            printf("=======================================\r\n");
            printf("*************Hi3861_demo**************\r\n");
            printf("=======================================\r\n");

            memset_s(uart_buff, sizeof(uart_buff), 0, sizeof(uart_buff));
            IoTUartRead(WIFI_IOT_UART_IDX_1, uart_buff, UART_BUFF_SIZE);

            printf("Uart1 read data:\n");
            for(int i = 0;i<16;i++){
                printf(" %02x ",*(uart_buff+i));
            }
            printf("\n");

            //tcp部分
            if ((ret = send(new_fd, uart_buff, sizeof(uart_buff), 0)) == -1) {
                perror("send error\n ");
            }

            //判断部分
            //PM10
            if(uart_buff[11]>30&&uart_buff[11]!=0){
                IoTGpioSetOutputVal(GPIO_2, 1);
            }
            if(uart_buff[11]<15&&uart_buff[11]!=0){
                IoTGpioSetOutputVal(GPIO_2, 0);
            }
            //temperature
            if(uart_buff[12]>30&&uart_buff!=0){
                IoTGpioSetOutputVal(GPIO_1, 1);
            }
            if(uart_buff[12]<25&&uart_buff!=0){
                IoTGpioSetOutputVal(GPIO_1, 0);
            }
            //Humidity
            if(uart_buff[14]<80&&uart_buff!=0){
                IoTGpioSetOutputVal(GPIO_1, 1);
            }
            if(uart_buff[14]>85&&uart_buff!=0){
                IoTGpioSetOutputVal(GPIO_1, 0);
            }

            usleep(TASK_DELAY_2S);
        }
        close(sock_fd);
    }

}

/**
 * @brief 创建主线程
 *
 */
static void Hi3861_demoEntry(void)
{
    osThreadAttr_t attr;

    attr.name = "Hi3861_demo";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = UART_TASK_STACK_SIZE;
    attr.priority = UART_TASK_PRIO;

    if (osThreadNew((osThreadFunc_t)Hi3861_demo, NULL, &attr) == NULL) {
        printf("Failed to create Hi3861_demo!\n");
    }
}

APP_FEATURE_INIT(Hi3861_demoEntry);